﻿using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;

namespace MyServer.Common
{
    /// <summary>
    /// 数据侦听器基类
    /// </summary>
    public abstract class DataListenerBase
    {

        #region========私有变量========

        /// <summary>
        /// 线程锁对象
        /// </summary>
        private static object lockobj = new object();

        /// <summary>
        /// 关闭标识
        /// </summary>
        private bool IsStop = false;

        #endregion

        #region==========属性==========

        /// <summary>
        /// 表示与数据侦听器关联的数据收发中心
        /// </summary>
        public DataCenterBase Center { get; protected set; }

        /// <summary>
        /// 表示数据侦听器的主侦听工作
        /// </summary>
        protected Task ListenMainTask { get; set; }

        /// <summary>
        /// 表示侦听器目前侦听的客户端列表
        /// </summary>
        protected ArrayList ListenQueue { get; set; }

        /// <summary>
        /// 获取或设置侦听器侦听的频率
        /// </summary>
        public int ListenRate { get; set; }
        
        /// <summary>
        /// 获取或设置侦听器的超时时间
        /// </summary>
        public int ListenTimeOutValue { get; set; }

        #endregion

        #region========公有委托========

        /// <summary>
        /// 为数据可用事件提供委托
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public delegate void DataAvailableEventHandler(object sender,ref DataListenerEventArgs e);

        /// <summary>
        /// 为监听超时事件提供委托
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public delegate void ListenTimeOutEventHandler(object sender, ref DataListenerEventArgs e);

        #endregion

        #region==========事件==========

        /// <summary>
        /// 当数据可用时触发的事件
        /// </summary>
        public event DataAvailableEventHandler DataAvailable;

        /// <summary>
        /// 当数据监听超时时触发的事件
        /// </summary>
        public event ListenTimeOutEventHandler ListenTimeOut;

        #endregion

        #region========私有函数========

        /// <summary>
        /// 开始侦听
        /// </summary>
        protected void DoListen()
        {
            while (IsStop == false)
            {
                lock (ListenQueue)
                {
                    foreach (ListenItem obj in ListenQueue.ToArray())
                    {
                        int datal = CheckDataAvilable(obj.Connect);
                        if (datal > 0)
                        {

                            DataPackageCollection col = new DataPackageCollection("", PackageCollectionType.ForRecive);
                            col.Tag = obj.Connect;
                            DataListenerEventArgs e = new DataListenerEventArgs(col, datal,obj.Connect);

                            if (DataAvailable != null)
                                DataAvailable(this, ref e);

                            if (e.IsCancel)
                            {
                                ClearData(obj.Connect);
                            }
                            else
                            {
                                this.ListenQueue.Remove(obj);
                            }
                        }
                        else
                        {
                            obj.WaitedTime += ListenRate;
                            if (obj.WaitedTime >= ListenTimeOutValue && ListenTimeOutValue!=-1)
                            {
                                DataListenerEventArgs e1=new DataListenerEventArgs(null,datal,obj.Connect);
                                if (ListenTimeOut != null)
                                { 
                                    ListenTimeOut(this, ref e1); 
                                }
                                if(!e1.IsCancel)
                                {
                                    ListenQueue.Remove(obj);
                                }
                            }
                        }
                    }
                }
                System.Threading.Thread.Sleep(ListenRate);
            }
        }

        #endregion

        #region========抽象函数========

        /// <summary>
        /// 检查指定的客户端有无数据
        /// </summary>
        /// <param name="Client">要检查的客户端</param>
        /// <returns>当前客户端的挂起的数据量</returns>
        public abstract int CheckDataAvilable(object Client);

        /// <summary>
        /// 清除目标客户端的请求数据
        /// </summary>
        /// <param name="Client"></param>
        /// <returns></returns>
        public abstract bool ClearData(object Client);

        #endregion

        #region========构造函数========

        /// <summary>
        /// 通过指定的数据中心创建数据侦听器实例
        /// </summary>
        /// <param name="Center">绑定的数据中心</param>
        public DataListenerBase(DataCenterBase Center)
        {
            this.Center = Center;
            this.ListenMainTask = new Task(DoListen);
            this.ListenQueue = System.Collections.ArrayList.Synchronized(new ArrayList());
            this.ListenRate = 10;
            this.ListenTimeOutValue = 10000;
        }

        #endregion

        #region========公有函数========

        /// <summary>
        /// 开启数据侦听器
        /// </summary>
        /// <returns></returns>
        public bool Start()
        {
            if (this.ListenMainTask.Status == TaskStatus.RanToCompletion)
                this.ListenMainTask = new Task(DoListen);
            this.ListenMainTask.Start();
            return true;
        }

        /// <summary>
        /// 停止数据侦听器
        /// </summary>
        /// <returns></returns>
        public bool Stop()
        {
            IsStop = true;
            while (ListenMainTask.Status == TaskStatus.Running)
            {
                System.Threading.Thread.Sleep(10);
            }
            return true;
        }

        /// <summary>
        /// 添加链接至侦听器中
        /// </summary>
        /// <param name="connect">要添加的链接</param>
        /// <returns></returns>
        public virtual bool AddConnect(object connect)
        {
            lock(ListenQueue)
            {
                foreach(ListenItem ci in ListenQueue)
                {
                    if (ci.Connect == connect)
                        return true;
                }
                ListenItem c = new ListenItem(connect);
                ListenQueue.Add(c);
            }
            return true;
        }
        /// <summary>
        /// 从侦听器中移除链接
        /// </summary>
        /// <param name="connect">要移除的链接</param>
        /// <returns></returns>

        public virtual bool RemoveConnect(object connect)
        {
            lock(ListenQueue)
            {
                foreach(ListenItem ci in ListenQueue)
                {
                    if(ci.Connect==connect)
                    {
                        ListenQueue.Remove(ci);
                        return true;
                    }
                }
            }
            return true;
        }

        /// <summary>
        /// 获取侦听器中的链接数目
        /// </summary>
        /// <returns></returns>
        public int GetConnectCount()
        {
            return ListenQueue.Count;
        }

        /// <summary>
        /// 获取指定连接的侦听信息
        /// </summary>
        /// <param name="con"></param>
        /// <returns></returns>
        public ListenItem GetInfo(object con)
        {
            foreach(ListenItem li in ListenQueue)
            {
                if(li.Connect==con)
                {
                    return li;
                }
            }
            return null;
        }

        #endregion

    }
}
